package com.heyige.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.heyige.dto.ChatHistoryDto;
import com.heyige.entity.ChatHistory;
import com.heyige.exception.BusinessException;
import com.heyige.exception.ErrorCode;
import com.heyige.mapper.ChatHistoryMapper;
import com.heyige.service.ChatHistoryService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;

import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;
import java.util.UUID;

@Slf4j
@Service("chatHistoryService")
@RequiredArgsConstructor
public class ChatHistoryServiceImpl extends ServiceImpl<ChatHistoryMapper, ChatHistory> implements ChatHistoryService {

    private final ChatHistoryMapper chatHistoryMapper;

    /**
     * 保存聊天记录
     *
     * @param userId    用户ID
     * @param role      角色
     * @param content   内容
     * @param model     模型
     * @param tokens    token数量
     * @param sessionId 会话ID
     * @return 聊天记录
     */
    public ChatHistory saveChatHistory(Long userId, String role, String content, String model, Integer tokens, String sessionId) {
        ChatHistory chatHistory = new ChatHistory();
        chatHistory.setUserId(userId);
        chatHistory.setRole(role);
        chatHistory.setContent(content);
        chatHistory.setModel(model);
        chatHistory.setTokens(tokens);
        // 如果没有提供会话ID，则生成一个新的
        if (!StringUtils.hasText(sessionId)) {
            sessionId = generateSessionId();
        }
        chatHistory.setSessionId(sessionId);
        chatHistoryMapper.insert(chatHistory);
        log.debug("保存聊天记录: 用户 {}, 角色 {}, 内容长度 {}, 模型 {}", userId, role, content.length(), model);
        return chatHistory;
    }

    /**
     * 保存用户消息
     *
     * @param userId    用户ID
     * @param content   内容
     * @param model     模型
     * @param sessionId 会话ID
     * @return 聊天记录
     */
    @Transactional(rollbackFor = Exception.class)
    @Override
    public ChatHistory saveUserMessage(Long userId, String content, String model, String sessionId) {
        return saveChatHistory(userId, ChatHistory.Role.USER.name(), content, model, 0, sessionId);
    }

    /**
     * 保存助手消息
     *
     * @param userId    用户ID
     * @param content   内容
     * @param model     模型
     * @param tokens    token数量
     * @param sessionId 会话ID
     * @return 聊天记录
     */
    @Transactional(rollbackFor = Exception.class)
    @Override
    public ChatHistory saveAssistantMessage(Long userId, String content, String model, Integer tokens, String sessionId) {
        return saveChatHistory(userId, ChatHistory.Role.ASSISTANT.name(), content, model, tokens, sessionId);
    }

    /**
     * 保存系统消息
     *
     * @param userId    用户ID
     * @param content   内容
     * @param sessionId 会话ID
     * @return 聊天记录
     */
    @Transactional(rollbackFor = Exception.class)
    @Override
    public ChatHistory saveSystemMessage(Long userId, String content, String sessionId) {
        return saveChatHistory(userId, ChatHistory.Role.SYSTEM.name(), content, null, 0, sessionId);
    }

    /**
     * 获取用户的聊天历史列表
     *
     * @param userId   用户ID
     * @param pageNum  分页参数
     * @param pageSize 分页参数
     * @return 聊天历史列表
     */
    public IPage<ChatHistoryDto.ChatHistoryResponse> getUserChatHistory(Long userId, Integer pageNum, Integer pageSize) {
        Page<ChatHistory> chatHistories = chatHistoryMapper.selectPage(new Page<>(pageNum, pageSize),
                new LambdaQueryWrapper<ChatHistory>().eq(ChatHistory::getUserId, userId)
                        .eq(ChatHistory::getIsDeleted, false)
                        .orderByDesc(ChatHistory::getCreatedAt)
        );
        return chatHistories.convert(this::buildChatHistoryResponse);
    }

    /**
     * 根据会话ID获取聊天历史列表
     *
     * @param userId    用户ID
     * @param sessionId 会话ID
     * @param pageNum   分页参数
     * @param pageSize  分页参数
     * @return 聊天历史列表
     */
    public IPage<ChatHistoryDto.ChatHistoryResponse> getChatHistoryBySession(Long userId, String sessionId, Integer pageNum, Integer pageSize) {
        Page<ChatHistory> chatHistories = chatHistoryMapper.selectPage(new Page<>(pageNum, pageSize),
                new LambdaQueryWrapper<ChatHistory>().eq(ChatHistory::getUserId, userId).eq(ChatHistory::getIsDeleted, false)
                        .eq(ChatHistory::getSessionId, sessionId)
                        .orderByAsc(ChatHistory::getCreatedAt));
        return chatHistories.convert(this::buildChatHistoryResponse);
    }

    /**
     * 获取用户的会话列表
     *
     * @param userId   用户ID
     * @param pageNum  当前页
     * @param pageSize 页大小
     * @return 会话列表
     */
    public Page<ChatHistoryDto.SessionResponse> getUserSessions(Long userId, Integer pageNum, Integer pageSize) {
        // 获取用户的所有会话ID
        List<String> sessionIds = chatHistoryMapper.selectList(
                        new LambdaQueryWrapper<ChatHistory>().eq(ChatHistory::getUserId, userId).eq(ChatHistory::getIsDeleted, false))
                .stream().map(ChatHistory::getSessionId).distinct().toList();

        // 为每个会话ID创建会话响应
        List<ChatHistoryDto.SessionResponse> sessions = new ArrayList<>();
        for (String sessionId : sessionIds) {
            // 获取会话的最后一条消息
            LambdaQueryWrapper<ChatHistory> queryWrapper = new LambdaQueryWrapper<ChatHistory>()
                    .eq(ChatHistory::getUserId, userId).eq(ChatHistory::getSessionId, sessionId)
                    .eq(ChatHistory::getIsDeleted, false)
                    .orderByDesc(ChatHistory::getCreatedAt);
            ChatHistory lastMessage = chatHistoryMapper.selectOne(queryWrapper);

            // 获取会话的消息数量
            Long messageCount = chatHistoryMapper.selectCount(queryWrapper);

            // 创建会话响应
            ChatHistoryDto.SessionResponse session = new ChatHistoryDto.SessionResponse();
            session.setSessionId(sessionId);
            session.setLastMessage(lastMessage.getContent());
            session.setLastMessageTime(lastMessage.getCreatedAt());
            session.setMessageCount(messageCount.intValue());

            sessions.add(session);
        }

        // 分页处理
        int start = (pageNum - 1) * pageSize;
        int end = Math.min((start + pageSize), sessions.size());

        List<ChatHistoryDto.SessionResponse> pageContent = sessions.subList(start, end);
        Page<ChatHistoryDto.SessionResponse> page = new Page<>(pageNum, pageSize);
        page.setRecords(pageContent);
        page.setTotal(sessions.size());

        return page;
    }

    /**
     * 删除聊天记录
     *
     * @param id     聊天记录ID
     * @param userId 用户ID
     */
    @Transactional(rollbackFor = Exception.class)
    @Override
    public void deleteChatHistory(Long id, Long userId) {
        // 检查聊天记录是否存在且属于该用户
        ChatHistory chatHistory = chatHistoryMapper.selectOne(
                new LambdaQueryWrapper<ChatHistory>()
                        .eq(ChatHistory::getId, id)
                        .eq(ChatHistory::getUserId, userId)
                        .eq(ChatHistory::getIsDeleted, false)
        );
        if (chatHistory == null) {
            throw new BusinessException(ErrorCode.NOT_FOUND, "聊天记录不存在或无权限访问");
        }

        // 软删除聊天记录
        chatHistory.setIsDeleted(true);
        chatHistoryMapper.updateById(chatHistory);

        log.info("用户 {} 删除聊天记录: {}", userId, id);
    }

    /**
     * 删除会话的所有聊天记录
     *
     * @param userId    用户ID
     * @param sessionId 会话ID
     */
    @Transactional(rollbackFor = Exception.class)
    @Override
    public void deleteChatHistoryBySession(Long userId, String sessionId) {
        // 检查会话是否存在且属于该用户
        List<ChatHistory> chatHistories = chatHistoryMapper.selectList(new LambdaQueryWrapper<ChatHistory>()
                .eq(ChatHistory::getUserId, userId)
                .eq(ChatHistory::getSessionId, sessionId)
                .eq(ChatHistory::getIsDeleted, false)
        );
        if (chatHistories.isEmpty()) {
            throw new BusinessException(ErrorCode.NOT_FOUND, "会话不存在或无权限访问");
        }

        // 软删除会话的所有聊天记录
        for (ChatHistory chatHistory : chatHistories) {
            chatHistory.setIsDeleted(true);
            chatHistoryMapper.updateById(chatHistory);
        }

        log.info("用户 {} 删除会话 {} 的所有聊天记录", userId, sessionId);
    }

    /**
     * 删除用户的所有聊天记录
     *
     * @param userId 用户ID
     */
    @Transactional(rollbackFor = Exception.class)
    @Override
    public void deleteAllChatHistory(Long userId) {
        // 获取用户的所有聊天记录
        List<ChatHistory> chatHistories = chatHistoryMapper.selectList(new LambdaQueryWrapper<ChatHistory>()
                .eq(ChatHistory::getUserId, userId).eq(ChatHistory::getIsDeleted, false));

        // 软删除用户的所有聊天记录
        for (ChatHistory chatHistory : chatHistories) {
            chatHistory.setIsDeleted(true);
            chatHistoryMapper.updateById(chatHistory);
        }

        log.info("用户 {} 删除所有聊天记录", userId);
    }

    /**
     * 清除指定时间之前的聊天记录
     *
     * @param userId     用户ID
     * @param beforeTime 时间
     */
    @Transactional(rollbackFor = Exception.class)
    @Override
    public void clearChatHistoryBeforeTime(Long userId, LocalDateTime beforeTime) {
        // 获取指定时间之前的所有聊天记录
        List<ChatHistory> chatHistories = chatHistoryMapper.selectList(new LambdaQueryWrapper<ChatHistory>()
                .eq(ChatHistory::getUserId, userId)
                .eq(ChatHistory::getIsDeleted, false)
                .lt(ChatHistory::getCreatedAt, beforeTime)
        );
        // 软删除这些聊天记录
        for (ChatHistory chatHistory : chatHistories) {
            chatHistory.setIsDeleted(true);
            chatHistoryMapper.updateById(chatHistory);
        }

        log.info("用户 {} 清除 {} 之前的所有聊天记录", userId, beforeTime);
    }

    /**
     * 获取聊天统计信息
     *
     * @param userId 用户ID
     * @return 聊天统计信息
     */
    public ChatHistoryDto.StatisticsResponse getChatStatistics(Long userId) {
        ChatHistoryDto.StatisticsResponse response = new ChatHistoryDto.StatisticsResponse();
        List<ChatHistory> list = this.list(new LambdaQueryWrapper<ChatHistory>()
                .eq(ChatHistory::getUserId, userId)
                .eq(ChatHistory::getIsDeleted, false)
                .orderByDesc(ChatHistory::getCreatedAt)
        );
        if (CollectionUtils.isEmpty(list)) {
            return response;
        }
        // 获取总消息数量
        response.setTotalMessages(list.size());
        // 获取会话数量
        response.setSessionCount(list.stream().map(ChatHistory::getSessionId).distinct().count());
        // 获取总token数量
        response.setTotalTokens(list.stream().map(ChatHistory::getTokens).reduce(0, Integer::sum));
        // 获取最早的消息时间
        LocalDateTime firstMessageTime = list.get(list.size() - 1).getCreatedAt();
        response.setFirstMessageTime(firstMessageTime);
        // 获取最晚的消息时间
        LocalDateTime lastMessageTime = list.get(0).getCreatedAt();
        response.setLastMessageTime(lastMessageTime);
        return response;
    }

    /**
     * 生成会话ID
     *
     * @return 会话ID
     */
    private String generateSessionId() {
        return "session_" + System.currentTimeMillis() + "_" + UUID.randomUUID().toString().substring(0, 8);
    }

    /**
     * 构建聊天历史响应
     *
     * @param chatHistory 聊天历史实体
     * @return 聊天历史响应
     */
    private ChatHistoryDto.ChatHistoryResponse buildChatHistoryResponse(ChatHistory chatHistory) {
        ChatHistoryDto.ChatHistoryResponse response = new ChatHistoryDto.ChatHistoryResponse();
        response.setId(chatHistory.getId());
        response.setUserId(chatHistory.getUserId());
        response.setSessionId(chatHistory.getSessionId());
        response.setRole(chatHistory.getRole());
        response.setContent(chatHistory.getContent());
        response.setModel(chatHistory.getModel());
        response.setTokens(chatHistory.getTokens());
        response.setCreatedAt(chatHistory.getCreatedAt());
        return response;
    }
}